/*
	This file is part of AVRCppLib.

    AVRCppLib is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    AVRCppLib is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with AVRCppLib.  If not, see <http://www.gnu.org/licenses/>.

    Copyright (C) Maxime Lemonnier 2007-2011
 */

#ifndef EXTERNALINTERRUPTSCOMPATIBILITY_H_
#define EXTERNALINTERRUPTSCOMPATIBILITY_H_

#include "../ExternalInterrupts.h"
#include "../../CallbackServers/FastCallbackServer.h"
#include <avr/interrupt.h>

#if __AVR_ATmega128__ || __AVR_ATmega1280__//TODO : other devices

#define EXTERNAL_INT0
#define INT0_vect_number 1
#define ISC_EICR0 	EICRA
#define EIMSK0		EIMSK
#define EIFR0		EIFR

#define EXTERNAL_INT1
#define INT1_vect_number 2
#define ISC_EICR1 	EICRA
#define EIMSK1		EIMSK
#define EIFR1		EIFR

#define EXTERNAL_INT2
#define INT2_vect_number 3
#define ISC_EICR2 	EICRA
#define EIMSK2		EIMSK
#define EIFR2		EIFR

#define EXTERNAL_INT3
#define INT3_vect_number 4
#define ISC_EICR3 	EICRA
#define EIMSK3		EIMSK
#define EIFR3		EIFR

#define EXTERNAL_INT4
#define INT4_vect_number 5
#define ISC_EICR4 	EICRB
#define EIMSK4		EIMSK
#define EIFR4		EIFR

#define EXTERNAL_INT5
#define INT5_vect_number 6
#define ISC_EICR5 	EICRB
#define EIMSK5		EIMSK
#define EIFR5		EIFR

#define EXTERNAL_INT6
#define INT6_vect_number 7
#define ISC_EICR6 	EICRB
#define EIMSK6		EIMSK
#define EIFR6		EIFR

#define EXTERNAL_INT7
#define INT7_vect_number 8
#define ISC_EICR7 	EICRB
#define EIMSK7		EIMSK
#define EIFR7		EIFR

#endif

#define EXTERNAL_INT_CASE(number) \
	case number : 	static ExternalInterrupt * instance##number;\
					if(isNull(instance##number))\
						instance##number = new ExternalInterrupt(INT##number##_vect_number, &ISC_EICR##number, InterruptSenseModes::RISING_EDGE, buildMask(ISC##number##0, ISC##number##1), &EIMSK##number, INT##number, &EIFR##number, INTF##number);\
					instance = instance##number;\
					break

#define EXTERNAL_INT_ISR(number) \
ISR(INT##number##_vect)\
{\
	FastCallbackServer::getInstance()->dispatch(INT##number##_vect_number);\
}\

ExternalInterrupt * ExternalInterrupt::getInstance(size_t number)
{

	static ExternalInterrupt * instance;

	switch (number)
	{

#ifdef EXTERNAL_INT0
				EXTERNAL_INT_CASE(0);
#endif
#ifdef EXTERNAL_INT1
				EXTERNAL_INT_CASE(1);
#endif
#ifdef EXTERNAL_INT2
				EXTERNAL_INT_CASE(2);
#endif
#ifdef EXTERNAL_INT3
				EXTERNAL_INT_CASE(3);
#endif
#ifdef EXTERNAL_INT4
				EXTERNAL_INT_CASE(4);
#endif
#ifdef EXTERNAL_INT5
				EXTERNAL_INT_CASE(5);
#endif
#ifdef EXTERNAL_INT6
				EXTERNAL_INT_CASE(6);
#endif
#ifdef EXTERNAL_INT7
				EXTERNAL_INT_CASE(7);
#endif

	default :	instance = NULL;

	}

	return instance;

}

#ifdef EXTERNAL_INT0
EXTERNAL_INT_ISR(0);
#endif
#ifdef EXTERNAL_INT1
EXTERNAL_INT_ISR(1);
#endif
#ifdef EXTERNAL_INT2
EXTERNAL_INT_ISR(2);
#endif
#ifdef EXTERNAL_INT3
EXTERNAL_INT_ISR(3);
#endif
#ifdef EXTERNAL_INT4
EXTERNAL_INT_ISR(4);
#endif
#ifdef EXTERNAL_INT5
EXTERNAL_INT_ISR(5);
#endif
#ifdef EXTERNAL_INT6
EXTERNAL_INT_ISR(6);
#endif
#ifdef EXTERNAL_INT7
EXTERNAL_INT_ISR(7);
#endif

#endif /* EXTERNALINTERRUPTSCOMPATIBILITY_H_ */
